package jp.sourceforge.akjrcp.imageedit;



import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import javax.imageio.ImageIO;

import jp.sourceforge.akjrcp.imageedit.ImageListView.SelectFile;
import jp.sourceforge.akjrcp.imageedit.figures.LineFigure;
import jp.sourceforge.akjrcp.imageedit.figures.OvalFigure;
import jp.sourceforge.akjrcp.imageedit.figures.RectangleFigure;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.FocusBorder;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.ViewPart;



/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

public class ImageEditView extends ViewPart implements ISelectionListener{
	public static Log log = LogFactory.getLog(ImageEditView.class);

	public static final String ID = ImageEditView.class.getName();

	private ScrolledComposite sc;

	private ImageFigure imageFigure;

	private RectangleFigure clip;

	private FigureCanvas canvas;

	private Text baseName;

	private Spinner counter;

	//private ImageCanvas canvas;

	public FigureMover figureMover=new FigureMover();

	private Button ovalButton;

	private Button lineButton;

	private Panel figurePanel;

	private CCombo imagePersent;

	private Button selectButton;
	
	public class DelKeyDeleteFigure implements KeyListener{



		public void keyPressed(KeyEvent e) {
			// TODO Auto-generated method stub
			
		}

		public void keyReleased(KeyEvent e) {
			//System.out.println(e);
			if(e.keyCode==127){//delete
				//System.out.println("del");
				figureMover.deleteFigure();
			}
		}
		
	}
	public static BufferedImage swtImageToAwtImage(Image image){
	
		
		ImageData data=image.getImageData();
		BufferedImage bimage=new BufferedImage(image.getBounds().width,image.getBounds().height,BufferedImage.TYPE_INT_ARGB);
		
		WritableRaster raster=bimage.getRaster();
		for(int i=0;i<image.getBounds().width;i++){
			for(int j=0;j<image.getBounds().height;j++){
				int color=data.getPixel(i,j);
				int int_rgb[]=new int[]{0xff&color,0xff&color>>8,0xff&color>>16,255};
				//System.out.println(int_rgb[0]+","+int_rgb[1]+","+int_rgb[0]);
				int x=i;
				int y=j;
				raster.setPixel(x,y,int_rgb);
			}
		}
		return bimage;
	}
	public void drawFiguresToGraphics2D(Graphics2D g2,boolean isSelectedArea){
		HashMap renderringHints = new HashMap(); 

		

		renderringHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
		renderringHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 

		renderringHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 

		

		renderringHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 

		

		renderringHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); 
		
		renderringHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 

		renderringHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

		g2.setRenderingHints(renderringHints);
		
		
		
		//draw image]
		
		Image image=imageFigure.getImage();
		BufferedImage bimage=swtImageToAwtImage(image);
		int imgw=(int)(image.getBounds().width*imageFigure.getZoom());
		int imgh=(int)(image.getBounds().height*imageFigure.getZoom());
		int drawx=0;
		int drawy=0;
		if(isSelectedArea){
			drawx-=clip.getLocation().x;
			drawy-=clip.getLocation().y;
		}
		g2.drawImage(bimage,drawx,drawy,imgw,imgh,null);
		//g2.drawImage
		
		Iterator iterator=figurePanel.getChildren().iterator();
		while(iterator.hasNext()){
			Figure figure=(Figure) iterator.next();
			if(figure instanceof OvalFigure){
				g2.setColor(new java.awt.Color(255,0,0));
				g2.setStroke(new BasicStroke(3));
				Rectangle rect=figure.getClientArea();
				if(isSelectedArea){
					rect.x-=clip.getLocation().x;
					rect.y-=clip.getLocation().y;
				}
				g2.drawOval(rect.x, rect.y, rect.width, rect.height);
			}else if(figure instanceof LineFigure){
				g2.setColor(new java.awt.Color(255,0,0));
				g2.setStroke(new BasicStroke(3));
				Rectangle rect=figure.getClientArea();
				if(isSelectedArea){
					rect.x-=clip.getLocation().x;
					rect.y-=clip.getLocation().y;
				}
				g2.drawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
			}
		}
	}
	public class PersetnChange implements SelectionListener{

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			String item=imagePersent.getItem(imagePersent.getSelectionIndex());
			double persent=Double.parseDouble(item.substring(0,item.length()-1))/100;
			imageFigure.setZoom(persent);
			canvas.setSize(imageFigure.getPreferredSize().width,imageFigure.getPreferredSize().height);
			//imageFigure.getParent().repaint();
			canvas.redraw();
		}
	
	}
	public class SaveClip implements SelectionListener{
		private boolean selection;
		public SaveClip(boolean selection){
			this.selection=selection;
		}
		public void widgetSelected(SelectionEvent e) {
			
			Rectangle rect=null;
			
			
			//System.out.println(rect);
			Image image=imageFigure.getImage();
			if(selection)
			rect=clip.getBounds();
			else{
				int imgw=(int)(image.getBounds().width*imageFigure.getZoom());
				int imgh=(int)(image.getBounds().height*imageFigure.getZoom());
				rect=new Rectangle(0,0,imgw,imgh);
			}
			//ImageData data=image.getImageData();
			
			
			//copy image.
			BufferedImage bimage=new BufferedImage(rect.width,rect.height,BufferedImage.TYPE_INT_ARGB);
			/*
			WritableRaster raster=bimage.getRaster();
			for(int i=rect.x;i<rect.x+rect.width;i++){
				for(int j=rect.y;j<rect.y+rect.height;j++){
					int color=data.getPixel(i,j);
					int int_rgb[]=new int[]{0xff&color,0xff&color>>8,0xff&color>>16,255};
					//System.out.println(int_rgb[0]+","+int_rgb[1]+","+int_rgb[0]);
					int x=i-rect.x;
					int y=j-rect.y;
					raster.setPixel(x,y,int_rgb);
				}
			}*/
			
			
			//drawOval
			Graphics2D g2=(Graphics2D) bimage.getGraphics();
			drawFiguresToGraphics2D(g2,selection);//selection
			
			try {
				File nextFile=nextFile();
				log.info("save:"+nextFile);
				ImageIO.write(bimage,"png",nextFile);
			} catch (IOException e1) {
				
				e1.printStackTrace();
			}
			
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}
		
	}
	
	private File nextFile(){
		int count=counter.getSelection();
		File file=null;
		do {
			String path = System.getProperty("user.home")+"/"+"My Documents/My Pictures/" + baseName.getText()+"_" + toDigits(count)
			+ "."+"png";
			file=new File(path);
			count++;
		}while(file.exists());
		
		counter.setSelection(count);
		return file;
	}
	
	public String toDigits(int value){
		String result=""+value;
		while(result.length()<4){
			result="0"+result;
		}
		return result;
	}

	public void createPartControl(Composite root) {
		getSite().getPage().addSelectionListener(ImageListView.ID,(ISelectionListener) this);
		
		root.setLayout(new GridLayout(1,false));
		Composite rootPanel=new Composite(root,SWT.NULL);
		rootPanel.setLayout(new GridLayout(2,false));
		
		Group panel=new Group(rootPanel,SWT.NULL);
		panel.setLayout(new GridLayout(6,false));
		ovalButton = new Button(panel,SWT.RADIO);
		ovalButton.setText("oval");
		ovalButton.setSelection(true);
		
		lineButton = new Button(panel,SWT.RADIO);
		lineButton.setText("line");
		
		//Button bt3=new Button(panel,SWT.RADIO);
		//bt3.setText("line");
		selectButton = new Button(panel,SWT.RADIO);
		selectButton.setText("select");
		
		
		
		
		
		imagePersent = new CCombo(panel,SWT.READ_ONLY);
		imagePersent.add("100%");
		imagePersent.add("50%");
		imagePersent.add("25%");
		for(int i=90;i>=0;i-=10){
			imagePersent.add(i+"%");
		}
		imagePersent.select(0);
		
		imagePersent.addSelectionListener(new PersetnChange());
		
		Group saveGroup=new Group(rootPanel,SWT.NULL);
		saveGroup.setLayout(new GridLayout(4,true));
		saveGroup.setText("Save");
		
		baseName = new Text(saveGroup,SWT.NULL);
		GridData baseNameData=new GridData();
		baseNameData.minimumWidth=300;
		baseName.setLayoutData(baseNameData);
		
		counter = new Spinner (saveGroup, SWT.BORDER);
		counter.setMinimum(0);
		counter.setMaximum(1000);
		counter.setSelection(1);
		counter.setIncrement(1);
		counter.setPageIncrement(1);
		
		Button saveClip=new Button(saveGroup,SWT.PUSH);
		saveClip.setText("Selected Save");
		saveClip.addSelectionListener(new SaveClip(true));
		
		Button saveAll=new Button(saveGroup,SWT.PUSH);
		saveAll.setText("All Save");
		saveAll.addSelectionListener(new SaveClip(false));
		
		/*
		sc = new ScrolledComposite(root,SWT.V_SCROLL|SWT.H_SCROLL);
		sc.setLayoutData(new GridData(GridData.FILL_BOTH));
		sc.setBackground(new Color(null,0,0,255));
		sc.setLayout(null);
		canvas = new ImageCanvas(sc,SWT.NO_BACKGROUND);
		//canvas.setSize(400,400);
		setImage(new Image(null,"c:\\tmp\\test.jpg"));
		sc.setContent(canvas);
	//	sc.setContent(bt);
		//sc.setMinSize(400,400);
        sc.setExpandHorizontal(true);
        sc.setExpandVertical(true);
        */
		
		sc = new ScrolledComposite(root,SWT.V_SCROLL|SWT.H_SCROLL);
		sc.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		//canvas.setSize(100,100);
		
		sc.setLayoutData(new GridData(GridData.FILL_BOTH));
		sc.setLayout(new GridLayout(1,false));
		sc.setBackground(new Color(null,230,230,230));
		//FigureCanvas canvas = new FigureCanvas(shell);
		
		canvas = new FigureCanvas(sc,SWT.NO_BACKGROUND);
		canvas.addMouseMoveListener(new MouseMove());
		canvas.addMouseListener(new MouseClick());
		canvas.addKeyListener(new DelKeyDeleteFigure());
		sc.setContent(canvas);
		
	
		
		figurePanel = new Panel();
		figurePanel.setLayoutManager(new XYLayout());
		
		imageFigure = new ImageFigure(null);
		figurePanel.add(imageFigure);
		
		
		
		
		canvas.setContents(figurePanel);
		//canvas.setSize(imageFigure.getPreferredSize().width,imageFigure.getPreferredSize().height);
		clip = new RectangleFigure(0,0,100,100);
		figurePanel.add(clip);
		clip.addMouseListener(figureMover);
		clip.addMouseMotionListener(figureMover);
		//FigureMoveResize move=new FigureMoveResize();
		   
		
		//clip.addMouseListener(move);
		//clip.addMouseMotionListener(move);
		
		
		//p2.add(new OvalFigure(0,0,30,30));
	}
	
	  public void openImage(File file){
		  Image image=new Image(null,file.getAbsolutePath());
		  imageFigure.setImage(image);
		  canvas.setSize(imageFigure.getPreferredSize().width,imageFigure.getPreferredSize().height);
		  //reset rect.
		  clip.setSize(100,100);
		  clip.setLocation(new Point(0,0));
		  //remove ovals.
		  
		  //setbasename
		  String name=file.getParentFile().getName();
		  baseName.setText(name);
	  }
	  
	  public class MouseMove implements MouseMoveListener{

		public void mouseMove(org.eclipse.swt.events.MouseEvent e) {
			
			if(e.stateMask!=0){
				
				figureMover.moveOutSide(e.x,e.y);
			}
		}


		  
	  }
	  
	  public class MouseClick implements org.eclipse.swt.events.MouseListener{

		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
			if(ovalButton.getSelection()){
				OvalFigure figure=new OvalFigure(e.x-15,e.y-15,30,30);
				figure.addMouseListener(figureMover);
				figure.addMouseMotionListener(figureMover);
				
				//figure.addKeyListener(new DelKeyDeleteFigure());
				
				figurePanel.add(figure);
				figure.setFocusTraversable(true);
			}else if(lineButton.getSelection()){
				LineFigure figure=new LineFigure(e.x,e.y,30,30);
				figure.addMouseListener(figureMover);
				figure.addMouseMotionListener(figureMover);
				
				//figure.addKeyListener(new DelKeyDeleteFigure());
				
				figurePanel.add(figure);
			}else if(selectButton.getSelection()){
				clip.setLocation(new Point(e.x,e.y));
			}
		}

		public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
			
		}

		public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
			
		}
		  
	  }
	  
	  public interface ResizableFigure{
		  public boolean isResizeBox(Point point);
		  public void resize(int incrementWidth,int incrementHeight);
		 // public Dimension getMinBounds();
	  }
	  
	  public class FigureMover extends MouseMotionListener.Stub implements MouseListener{
		  private Figure currentFigure;
		  private Point lastPoint;
		  boolean resize;
		  
		  public void move(int x,int y){
			  if(currentFigure!=null){
				  if(lastPoint!=null){
					  Point newPoint=new Point(x,y);
					  Dimension delta = newPoint.getDifference(lastPoint);
					  lastPoint = newPoint;
					  
					  if(resize){
					       		ResizableFigure f=(ResizableFigure) currentFigure;
					       		f.resize(delta.width,delta.height);
					       		//currentFigure.setSize(Math.max(f.getMinBounds().width,currentFigure.getBounds().width+delta.width),Math.max(f.getMinBounds().height,currentFigure.getBounds().height+delta.height));
					           }
					  else{
					  currentFigure.setBounds(currentFigure.getBounds().getTranslated(delta.width, delta.height));
					  }
				  }
			  }
		  }
		  public void deleteFigure() {
			  log.info(currentFigure);
			if(currentFigure!=null){
				 log.info("delete");
				if(currentFigure instanceof OvalFigure){
					currentFigure.erase();
					currentFigure.getParent().remove(currentFigure);
				}else if(currentFigure instanceof LineFigure){
					currentFigure.erase();
					currentFigure.getParent().remove(currentFigure);
				}
			}
		}
		public void moveOutSide(int x,int y){
			  if(currentFigure!=null){
				  if(!currentFigure.containsPoint(x, y)){
					
					  move(x,y);
				  }
			  }
		  }
		public void mouseDoubleClicked(MouseEvent arg0) {
			
		}
		
		 public void mouseDragged(MouseEvent me) { 
			 move(me.x,me.y);
		 }
		
		public void mousePressed(MouseEvent me) {
			if(currentFigure!=null){
				currentFigure.setBorder(null);
				
			}
			
			currentFigure=(Figure) me.getSource();
			
			currentFigure.setBorder(new FocusBorder());
			
			lastPoint=new Point(me.x,me.y);
			if(currentFigure instanceof ResizableFigure){
				resize=((ResizableFigure)currentFigure).isResizeBox(lastPoint);
			}else{
				resize=false;
			}
			figurePanel.repaint();
		}
		
		public void mouseReleased(MouseEvent arg0) {
			//currentFigure=null;
			
			lastPoint=null;
		}
	  }
	  
	  
	/*
	  public class FigureMoveResize extends MouseMotionListener.Stub implements MouseListener{
		   Point last;
		   boolean isResize;
		 
		   public void mousePressed(MouseEvent me) {
			   last=new Point(me.x,me.y);
			   RectangleFigure f = ((RectangleFigure)me.getSource());
			   isResize=f.isResizeBox(last);
			   
			  
		   }
		   
		   public void mouseDragged(MouseEvent me) { 
			   
			   if(last!=null){
			   Point p = me.getLocation();
	           Dimension delta = p.getDifference(last);
	           last = p;
	           RectangleFigure f = ((RectangleFigure)me.getSource());
	           if(isResize){
	       // System.out.println(f.getBounds().getTranslated(delta.width, delta.height));
	        	f.resize(delta.width,delta.height);
	        	}else{
	           f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
	           }
			   }
		   }
		
		   
		public void mouseReleased(MouseEvent me) {
			//System.out.println("mouse-released");
			last=null;
			
		}
		public void mouseDoubleClicked(MouseEvent me) {
			
		}
	   }
	   */
	/*
	   public class FigureMove extends MouseMotionListener.Stub implements MouseListener{
		   Point last;
		
		 
		   public void mousePressed(MouseEvent me) {
			   last=new Point(me.x,me.y);
			  
			  
		   }
		   
		   public void mouseDragged(MouseEvent me) { 
			   
			   if(last!=null){
			   Point p = me.getLocation();
	           Dimension delta = p.getDifference(last);
	           last = p;
	           Figure f = ((Figure)me.getSource());
	          
	           f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
	           
			   }
		   }
		
		
		
		   
		public void mouseReleased(MouseEvent me) {
			//System.out.println("mouse-released");
			last=null;
		}
		public void mouseDoubleClicked(MouseEvent me) {
			
		}
	   }
	   
	   */
	

	   
	public class ImageFigure extends Figure{
		private Image image;
		private double zoom=1.0;
		public ImageFigure(Image image){
			setImage(image);
			setSize(100,100);
			setBorder(new LineBorder());
		}
		public Dimension getPreferredSize(int whint,int hhint){
			if(image==null){
				return new Dimension(0,0);
			}
			if(zoom==1.0){
			return new Dimension(image.getBounds().width,image.getBounds().height);
			}else{
				int w=(int)(image.getBounds().width*zoom);
				int h=(int)(image.getBounds().height*zoom);
				log.info("imageFigure:"+w+","+h);
			return new Dimension(w,h);
			}
		}
	    public void paintFigure(Graphics g){
	        
	       if(image!=null){
	    	   if(zoom==1.0){
	    		   g.drawImage(
	            image,0,0);  
	    	   }else{
	    		   
	    		   int w=(int)(image.getBounds().width*zoom);
				   int h=(int)(image.getBounds().height*zoom);
				   
					 g.drawImage(
					            image,0,0,image.getBounds().width,image.getBounds().height,0,0,w,h);
	    	   }
	       }
	    }
		public Image getImage() {
			return image;
		}
		public void setImage(Image image) {
			if(this.image!=null){
				this.image.dispose();//for memory
			}
			this.image = image;
			setSize(getPreferredSize());
			//System.out.println(getSize());
			
			repaint();
		}
		public double getZoom() {
			return zoom;
		}
		public void setZoom(double zoom) {
			this.zoom = zoom;
		}
	}
	/*
	public void setImage(Image image){
		canvas.setImage(image);
		sc.setMinSize(image.getBounds().width,image.getBounds().height);
	}
	
	

	public class ImageCanvas extends Canvas implements PaintListener{
		private Image image;
		
		public ImageCanvas(Composite parent, int style) {
			super(parent, style);
			// TODO Auto-generated constructor stub
			this.addPaintListener(this);
			this.setBackground(new Color(null,0,255,0));
		}

		public void paintControl(PaintEvent e) {
			e.gc.setBackground(new Color(null,225,225,225));
			e.gc.fillRectangle(0,0,this.getClientArea().width,this.getClientArea().height);
			if(image!=null){
				e.gc.drawImage(image,0,0);
			}
			//e.gc.setBackground(new Color(null,255,0,0));
			//e.gc.fillRectangle(0,0,400,400);
		}

		public Image getImage() {
			return image;
		}

		public void setImage(Image image) {
			this.image = image;
		}
		
	}*/
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
	
	}
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		SelectFile selectFile=(SelectFile) selection;
		openImage(selectFile.getFile());
	}

}